const cloud = require('wx-server-sdk');
/** @namespace process.env.Env */
cloud.init({ env: process.env.Env });
const db = cloud.database();
const _ = db.command;
const RELEASE_LOG_KEY = 'releaseLogKey';
cloud.init();

// cloud function entry function
exports.main = async (event) => {
    // the admin service must verify the permissions
    if (event.action !== 'checkAuthor' && event.action !== 'getLabelList' && event.action !== 'getClassifyList') {
        let result = await checkAuthor(event);
        if (!result) {
            return false;
        }
    }
    switch (event.action) {
        case 'checkAuthor': {
            return checkAuthor(event)
        }
        case 'addReleaseLog': {
            return addReleaseLog(event)
        }
        case 'updatePostsShowStatus': {
            return updatePostsShowStatus(event)
        }
        case 'updatePostsClassify': {
            return updatePostsClassify(event)
        }
        case 'updatePostsLabel': {
            return updatePostsLabel(event)
        }
        case 'upSertPosts': {
            return upSertPosts(event)
        }
        case 'addBaseLabel': {
            return addBaseLabel(event)
        }
        case 'addBaseClassify': {
            return addBaseClassify(event)
        }
        case 'deleteConfigById': {
            return deleteConfigById(event)
        }
        case 'changeCommentFlagById': {
            return changeCommentFlagById(event)
        }
        case 'getLabelList': {
            return getLabelList(event)
        }
        case 'getClassifyList': {
            return getClassifyList(event)
        }
        case 'deletePostById': {
            return deletePostById(event)
        }
        case 'updateBatchPostsLabel': {
            return updateBatchPostsLabel(event)
        }
        case 'updateBatchPostsClassify': {
            return updateBatchPostsClassify(event)
        }
        default:
            break
    }
};

/**
 * verify admin
 * @param {} event
 */
async function checkAuthor(event) {
    let authors = process.env.author;
    return authors.indexOf(event.userInfo.openId) !== -1;
}

/**
 * add new version log
 * @param {*} event
 */
async function addReleaseLog(event) {
    try {
        let collection = 'smallTechnology_logs';
        let data = {
            key: RELEASE_LOG_KEY,
            tag: '【' + event.log.releaseName + '版本更新',
            content: event.log,
            title: event.title,
            icon: 'formFill',
            color: 'blue',
            path: '../release/release',
            timestamp: Date.now(),
            datetime: new Date(Date.now() + (8 * 60 * 60 * 1000)).toFormat("YYYY-MM-DD HH24:MI"),
            // is empty for all users
            openId: '',
            type: 'system'
        };
        await db.collection(collection).add({
            data: data
        });
        return true;
    } catch (e) {
        console.info(e);
        return false;
    }

}

/**
 * update article display status
 * @param {*} event
 */
async function updatePostsShowStatus(event) {
    try {
        await db.collection('smallTechnology_posts').doc(event.id).update({
            data: {
                isShow: event.isShow
            }
        });
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * update article topic name
 * @param {*} event
 */
async function updatePostsClassify(event) {
    try {
        await db.collection('smallTechnology_posts').doc(event.id).update({
            data: {
                classify: event.classify
            }
        });
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * Update article topic name
 * @param {*} event
 */
async function updatePostsLabel(event) {
    try {
        await db.collection('smallTechnology_posts').doc(event.id).update({
            data: {
                label: event.label
            }
        });
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * 新增or更新文章
 * @param {*} event
 */
async function upSertPosts(event) {
    try {
        let collection = "smallTechnology_posts";
        if (event.id === "") {
            await db.collection(collection).add({
                data: event.post
            });
        } else {
            await db.collection(collection).doc(event.id).update({
                data: event.post
            });
        }
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * 新增基础标签
 * @param {*} event
 */
async function addBaseLabel(event) {
    let key = "basePostsLabels";
    let collection = "smallTechnology_config";
    let result = await db.collection(collection).where({
        key: key,
        value: event.labelName
    }).get();
    if (result.data.length > 0) {
        return false
    } else {
        await db.collection(collection).add({
            data: {
                key: key,
                timestamp: Date.now(),
                value: event.labelName
            }
        });
        return true;
    }
}

/**
 * New basic topics
 * @param {} event
 */
async function addBaseClassify(event) {
    let key = "basePostsClassify";
    let collection = "smallTechnology_config";
    let classifyData = {
        classifyName: event.classifyName,
        classifyDesc: event.classifyDesc
    };
    let result = await db.collection(collection).where({
        key: key,
        value: _.eq(classifyData)
    }).get();
    if (result.data.length > 0) {
        return false
    } else {
        await db.collection(collection).add({
            data: {
                key: key,
                timestamp: Date.now(),
                value: classifyData
            }
        });
        return true;
    }
}

/**
 * delete configuration table data according to id
 * @param {*} event
 */
async function deleteConfigById(event) {
    try {
        await db.collection('smallTechnology_config').doc(event.id).remove();
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

async function deletePostById(event) {
    try {
        await db.collection('smallTechnology_posts').doc(event.id).remove();
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * delete comments by id
 * @param {*} event
 */
async function changeCommentFlagById(event) {
    try {
        let task1 = db.collection('smallTechnology_comments').doc(event.id).update({
            data: {
                flag: event.flag
            }
        });
        let task2 = db.collection('smallTechnology_posts').doc(event.postId).update({
            data: {
                totalComments: _.inc(event.count)
            }
        });
        await task1;
        await task2;
        return true;
    } catch (e) {
        console.error(e);
        return false;
    }
}

/**
 * 获取所有label集合
 * @param {*} event
 */
async function getLabelList(event) {
    const MAX_LIMIT = 100;
    const countResult = await db.collection('smallTechnology_config').where({
        key: 'basePostsLabels'
    }).count();
    const total = countResult.total;
    if (total === 0) {
        return {
            data: [],
            errMsg: "no label data",
        }
    }
    // 计算需分几次取
    const batchTimes = Math.ceil(total / 100);
    // 承载所有读操作的 promise 的数组
    const tasks = [];
    for (let i = 0; i < batchTimes; i++) {
        const promise = db.collection('smallTechnology_config').where({
            key: 'basePostsLabels'
        }).skip(i * MAX_LIMIT).limit(MAX_LIMIT).get();
        tasks.push(promise)
    }
    // 等待所有
    return (await Promise.all(tasks)).reduce((acc, cur) => {
        return {
            data: acc.data.concat(cur.data),
            errMsg: acc.errMsg,
        }
    })
}

/**
 * 获取所有label集合
 * @param {*} event
 */
async function getClassifyList(event) {
    const MAX_LIMIT = 100
    const countResult = await db.collection('smallTechnology_config').where({
        key: 'basePostsClassify'
    }).count();
    const total = countResult.total;
    if (total === 0) {
        return {
            data: [],
            errMsg: "no classify data",
        }
    }
    // 计算需分几次取
    const batchTimes = Math.ceil(total / 100)
    // 承载所有读操作的 promise 的数组
    const tasks = [];
    for (let i = 0; i < batchTimes; i++) {
        const promise = db.collection('smallTechnology_config').where({
            key: 'basePostsClassify'
        }).skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
        tasks.push(promise)
    }
    // 等待所有
    return (await Promise.all(tasks)).reduce((acc, cur) => {
        return {
            data: acc.data.concat(cur.data),
            errMsg: acc.errMsg,
        }
    })
}

/**
 * 批量保存标签信息
 * @param {*} event
 */
async function updateBatchPostsLabel(event) {
    console.info(event);
    for (let i = 0; i < event.posts.length; i++) {
        let result = await db.collection('smallTechnology_posts').doc(event.posts[i]).get()
        let oldLabels = result.data.label
        if (event.operate === 'add') {
            if (oldLabels.indexOf(event) > -1) {
                continue
            }
            await db.collection('smallTechnology_posts').doc(event.posts[i]).update({
                data: {
                    label: _.push([event.label])
                }
            })
        } else if (event.operate === 'delete') {

            var index = oldLabels.indexOf(event);
            if (index === -1) {
                continue
            }
            oldLabels.splice(index, 1);

            await db.collection('smallTechnology_posts').doc(event.posts[i]).update({
                data: {
                    label: oldLabels
                }
            })
        }
    }

    return true;
}

/**
 * 批量保存主题信息
 * @param {*} event
 */
async function updateBatchPostsClassify(event) {
    for (let i = 0; i < event.posts.length; i++) {
        if (event.operate === 'add') {
            await db.collection('smallTechnology_posts').doc(event.posts[i]).update({
                data: {
                    classify: event.classify
                }
            })
        } else if (event.operate === 'delete') {
            await db.collection('smallTechnology_posts').doc(event.posts[i]).update({
                data: {
                    classify: ""
                }
            })
        }
    }

    return true;
}

// /**
//  * 处理七牛token
//  * @returns {Promise<void>}
//  */
// async function getToken() {
//     // let accessKey = process.env.accessKey;
//     let accessKey = "";
//     let secretKey = "";
//     // process.env.secretKey;
//
//     let bucket = "";
//     // process.env.bucket;
//     var mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
//
//     var options = {
//         scope: bucket,
//     };
//     var putPolicy = new qiniu.rs.PutPolicy(options);
//     var uploadToken = putPolicy.uploadToken(mac);
//
//     return uploadToken;
//
// }